import java.io.BufferedWriter;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URLEncoder;

import org.apache.commons.io.FileUtils;
import org.catamarancode.zip.ZipCodeInfo;
import org.catamarancode.zip.client.ZipCodeServiceClient;
import org.htmlparser.Parser;
import org.htmlparser.filters.HasAttributeFilter;
import org.htmlparser.filters.TagNameFilter;
import org.htmlparser.tags.Bullet;
import org.htmlparser.tags.BulletList;
import org.htmlparser.tags.Div;
import org.htmlparser.tags.HeadingTag;
import org.htmlparser.tags.LinkTag;
import org.htmlparser.tags.ParagraphTag;
import org.htmlparser.tags.Span;
import org.htmlparser.util.NodeList;
import org.htmlparser.util.ParserException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Parse by looking for the string <a
 * href="/homeinspectors/California/Fallbrook.aspx">
 * 
 * @author mkvalsvik
 * 
 */
public class NachiInspectorListByStateDetailParser {

	private static Logger logger = LoggerFactory
			.getLogger(NachiInspectorListByStateDetailParser.class.getName());

	private static final String INPUT_DIR = "/mads/hobby/it/data/nachi/inspectors_by_state";

	private StringBuilder sb = null;

	private static ZipCodeServiceClient zipClient = null;

	public static void main(String[] args) {
		logger.debug("Starting..");

		zipClient = new ZipCodeServiceClient(
				"ec2-184-72-238-16.compute-1.amazonaws.com", "/catamaran-zip",
				8090, "clientA", "abcdabcdabcd1234");
		zipClient.init();

		BufferedWriter writer = null;
		try {
			writer = new BufferedWriter(new FileWriter(
					"extractedNachiInspectorDetails.tsv"));

			NachiInspectorListByStateDetailParser instance = new NachiInspectorListByStateDetailParser();
			File dir = new File(INPUT_DIR);
			//instance.parseDir(dir, writer);

			File file = new File(dir, "httpwwwnachiorgAK.html");
			instance.parseFile(file, writer);

		} catch (IOException e1) {
			logger.error("Error", e1);
		} catch (ParserException e) {
			logger.error("Error", e);
		} finally {
			try {
				writer.close();
			} catch (IOException e) {
				// ignore
			}
		}
	}

	public void parseDir(File dir, BufferedWriter writer)
			throws ParserException, IOException {

		File[] files = dir.listFiles();
		for (int i = 0; i < files.length; i++) {

			// Read into a string
			sb = new StringBuilder();
			if (files[i].getName().endsWith(".html")) {
				parseFile(files[i], writer);
				// return;
			}
		}
	}

	private char[] cbuf = new char[1024];

	public void parseFile(File file, BufferedWriter writer) throws IOException,
			ParserException {

		logger.debug("Parsing " + file.getAbsolutePath());
		char[] cbuf = new char[1024];

		// Read into a string
		String content = FileUtils.readFileToString(file);
		Parser parser = new Parser();
		parser.setInputHTML(content);
		parser.setEncoding("utf-8");
		NodeList nodeList = parser.parse(null);

		NodeList divNodes = nodeList.extractAllNodesThatMatch(
				new HasAttributeFilter("id", "content"), true);
		if (divNodes.size() < 1) {
			logger.warn(String.format("%s: Found no div named contentMain %d",
					file.getAbsolutePath(), divNodes.size()));
			return;
		}

		// Second div
		Div divTag = (Div) divNodes.elementAt(0);
		NodeList inspectorNodes = divTag.getChildren()
				.extractAllNodesThatMatch(new TagNameFilter("div"), false);
		if (inspectorNodes.size() < 1) {
			logger.warn(String.format(
					"%s: Found no inspector div tags inside div id=content %d",
					file.getAbsolutePath(), inspectorNodes.size()));
			return;
		}

		// Extract data fields
		for (int i = 0; i < inspectorNodes.size(); i++) {
			logger.debug(String.format("Processing inspector %d of %d", i,
					inspectorNodes.size()));
			Div div = (Div) inspectorNodes.elementAt(i);
			HeadingTag h4Tag = (HeadingTag) div.getChildren()
					.extractAllNodesThatMatch(new TagNameFilter("h4"), false)
					.elementAt(0);
			Span span = (Span) h4Tag.childAt(0);
			String name = span.getStringText();

			NodeList pTags = div.getChildren().extractAllNodesThatMatch(
					new TagNameFilter("p"));
			ParagraphTag companyTag = (ParagraphTag) pTags.elementAt(0);
			String company = companyTag.getStringText();

			ParagraphTag phoneTag = (ParagraphTag) pTags.elementAt(1);
			String phone = phoneTag.getStringText();

			ParagraphTag locationTag = (ParagraphTag) pTags.elementAt(2);
			String location = locationTag.getStringText();
			SimpleHtmlParser p = new SimpleHtmlParser(location);
			p.skipTag();
			String city = p.extractUntilTag();
			p.advance(2);
			String stateCode = p.extractNChars(2);

			// Lookup zip
			ZipCodeInfo info = zipClient.lookupZipCodeForCityAndState(city,
					stateCode);
			String zip = null;
			if (info != null) {
				zip = info.getZipCode();
			}

			String link = null;
			Div moreTag = (Div) div.getChildren().extractAllNodesThatMatch(
					new TagNameFilter("div"), false).elementAt(0);
			if (moreTag != null && moreTag.getChildren() != null) {
				BulletList list = (BulletList) moreTag.getChildren()
						.extractAllNodesThatMatch(new TagNameFilter("ul"),
								false).elementAt(0);
				Bullet b = (Bullet) list.getChildren()
						.extractAllNodesThatMatch(new TagNameFilter("li"),
								false).elementAt(0);
				if (b.getChildren() != null) {
					NodeList linkTagList = b.getChildren()
							.extractAllNodesThatMatch(new TagNameFilter("a"));
					if (linkTagList.size() > 0) {
						LinkTag linkTag = (LinkTag) linkTagList.elementAt(0);
						link = linkTag.extractLink();
					}
				}
			}

			String line = String.format("%s\t%s\t%s\t%s\t%s\t%s\t%s", name,
					company, phone, city, stateCode, zip, link);
			logger.info("Got data: " + line);

			writer.write(line);
			writer.newLine();
		}
	}
}
